package com.enba.boot.core.utils;

import com.alibaba.ttl.threadpool.TtlExecutors;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public final class ThreadLocalTtlUtils {
  private static volatile ExecutorService executorService = null;

  private ThreadLocalTtlUtils() {}

  private static ExecutorService getExecutorService() {
    if (null == executorService) {
      synchronized (ThreadLocalTtlUtils.class) {
        if (null == executorService) {
          executorService =
              TtlExecutors.getTtlExecutorService(
                  new ThreadPoolExecutor(
                      15,
                      20,
                      30L,
                      TimeUnit.SECONDS,
                      new SynchronousQueue(),
                      new CallerRunsPolicy()));
        }
      }
    }
    return executorService;
  }

  public static void execute(Runnable runnable) {
    getExecutorService().execute(runnable);
  }

  public static void execute(Runnable runnable, ThreadPoolExecutor threadPoolExecutor) {
    TtlExecutors.getTtlExecutorService(threadPoolExecutor).execute(runnable);
  }

  public static <T> T submit(Callable<T> task) throws ExecutionException, InterruptedException {
    return getExecutorService().submit(task).get();
  }

  public static <T> T submit(Callable<T> task, long timeout)
      throws InterruptedException, ExecutionException, TimeoutException {
    return getExecutorService().submit(task).get(timeout, TimeUnit.SECONDS);
  }

  public static <T> T submit(Callable<T> task, ThreadPoolExecutor threadPoolExecutor)
      throws ExecutionException, InterruptedException {
    return TtlExecutors.getTtlExecutorService(threadPoolExecutor).submit(task).get();
  }

  public static <T> T submit(Callable<T> task, ThreadPoolExecutor threadPoolExecutor, long timeout)
      throws ExecutionException, InterruptedException, TimeoutException {
    return TtlExecutors.getTtlExecutorService(threadPoolExecutor)
        .submit(task)
        .get(timeout, TimeUnit.SECONDS);
  }

  public static void main(String[] args)
      throws ExecutionException, InterruptedException, TimeoutException {
    String submit =
        ThreadLocalTtlUtils.submit(
            () -> {
              System.out.println(Thread.currentThread().getName());
              TimeUnit.SECONDS.sleep(10);
              return "123";
            },
            5);

    System.out.println(submit);
  }
}
